#include "Application.h"
namespace gl
{
  Application *Application::mInstance = nullptr;
  Application *Application::getInstance()
  {
    if (mInstance == nullptr)
    {
      mInstance = new Application();
    }

    return mInstance;
  }

  Application::Application() {}

  Application::~Application() {}

  bool Application::init(const int &width, const int &height)
  {
    mWidth = width;
    mHeight = height;
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    mWindow = glfwCreateWindow(mWidth, mHeight, "OpenGLStudy", NULL, NULL);
    if (mWindow == NULL)
    {
      return false;
    }

    glfwMakeContextCurrent(mWindow);

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
      std::cout << "Failed to initialize GLAD" << std::endl;
      return false;
    }

    glfwSetFramebufferSizeCallback(mWindow, frameBufferSizeCallback);

    glfwSetWindowUserPointer(mWindow, this);

    glfwSetKeyCallback(mWindow, keyCallback);

    return true;
  }

  bool Application::update()
  {
    if (glfwWindowShouldClose(mWindow))
    {
      return false;
    }
    glfwPollEvents();
    glfwSwapBuffers(mWindow);

    return true;
  }

  void Application::destroy() { glfwTerminate(); }

  void Application::frameBufferSizeCallback(GLFWwindow *window, int width,
                                            int height)
  {
    std::cout << "Resize" << std::endl;

    Application *self = (Application *)glfwGetWindowUserPointer(window);
    if (self->mResizeCallback != nullptr)
    {
      self->mResizeCallback(width, height);
    }
  }

  void Application::keyCallback(GLFWwindow *window, int key, int scancode,
                                int action, int mods)
  {
    Application *self = (Application *)glfwGetWindowUserPointer(window);
    if (self->mKeyBoardCallback != nullptr)
    {
      self->mKeyBoardCallback(key, action, mods);
    }
  }

}
